import 'package:logger/logger.dart';
import 'package:openvpn_flutter/openvpn_flutter.dart';

class OpenVPNService {
  final Logger _logger = Logger();
  final OpenVPN _openVpn = OpenVPN();
  bool _isInitialized = false;
  static bool isFirstInitialization = true;

  Future<void> init({
    required Function(String) onVPNStatusChanged,
    required Function(VpnStatus) onConnectionStatusChanged,
  }) async {
    if (_isInitialized) {
      _logger.i('OpenVPN already initialized');
      return;
    }

    try {
      await _openVpn.initialize(
        localizedDescription: 'My VPN',
        providerBundleIdentifier: 'com.example.vpn',
        lastStatus: onConnectionStatusChanged,
        lastStage: (stage) {
          onVPNStatusChanged(stage.toString().split('.').last.toUpperCase());
        },
      );
      _isInitialized = true;
      if (isFirstInitialization) {
        _logger.i('OpenVPN initialized successfully');
        isFirstInitialization = false;
      }
    } catch (e, stackTrace) {
      _isInitialized = false;
      _logger.e('OpenVPN initialization failed: $e\nStack trace: $stackTrace');
      rethrow;
    }
  }

  Future<void> connect(
    String ovpnContent,
    String keyContent, {
    String? username,
    String? password,
  }) async {
    if (!_isInitialized) {
      _logger.e('Connection failed: OpenVPN not initialized');
      throw Exception('OpenVPN not initialized');
    }

    try {
      String modifiedOvpnContent = ovpnContent;
      if (!ovpnContent.contains('<tls-auth>') &&
          !ovpnContent.contains('<tls-crypt>')) {
        modifiedOvpnContent += '\n<tls-auth>\n$keyContent\n</tls-auth>\n';
      }

      await _openVpn.connect(
        modifiedOvpnContent,
        'My VPN',
        username: username ?? '',
        password: password ?? '',
        certIsRequired: false,
      );
      _logger.i('VPN connection started');
    } catch (e, stackTrace) {
      _logger.e('VPN connection failed: $e\nStack trace: $stackTrace');
      rethrow;
    }
  }

  Future<void> disconnect() async {
    try {
      _openVpn.disconnect();
      _logger.i('VPN disconnected');
    } catch (e, stackTrace) {
      _logger.e('VPN disconnection failed: $e\nStack trace: $stackTrace');
      rethrow;
    }
  }
}
